package com.kaibes.platform.file.client;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.kaibes.platform.file.client.db.FileServer;
import com.kaibes.platform.file.client.db.FileServerService;
import com.kaibes.platform.file.client.util.FileServerUtils;

@Component
@EnableScheduling
public class FileServerPollingStrategy implements FileServerStrategy {

	@Autowired
	private FileServerService fileServerService;
	@Autowired
    private FileServerUtils fileServerUtils;
	
	private Stack<FileServer> serverStack = new Stack<>();
	private short priority = Short.MAX_VALUE;
	private short count;
	private FileServer fileServer;
	
	private List<Integer> disable = new ArrayList<>();
	
	@Override
	public FileServer getFileServer() {
		synchronized (this) {
			if (count == 0) {
				// 计数为0，获取新的服务器地址
				if (!serverStack.isEmpty()) {
					// 服务器栈不为空，获取一个服务器
					fileServer = serverStack.pop();
					count = fileServer.getPriority();
					return getFileServer();
				}
				// 获取服务器，屏蔽不可用的
				fileServer = fileServerService.getByLtPriorityAndNotIdList(priority, disable);
				if (fileServer != null) {
					priority = fileServer.getPriority();
					serverStack.addAll(fileServerService.listByPriorityAndNotIdList(priority, disable));
					return getFileServer();
				} else {
					if (priority == Short.MAX_VALUE) {
						// 一个可用的都没有
						// 释放掉不可用的，加快检查速度
						count = 0;
						disable.clear();
						return null;
					} else {
						priority = Short.MAX_VALUE;
						// 向下遍历
						return getFileServer();
					}
				}
			} else {
				fileServer = fileServerService.getById(fileServer.getId());
				if (fileServerUtils.test(fileServer)) {
					count -= 1;
					return fileServer;
				} else {
					count = 0;
					Integer id = fileServer.getId();
					if (!disable.contains(id)) {
						disable.add(id);
						System.err.println("server("+fileServer.getName()+") is disable.");
					}
					return getFileServer();
				}
			}
		}
	}
	
	@Scheduled(fixedRate=60 * 1000)
    private void configureTasks() {
		synchronized (this) {
			List<Integer> temp = new ArrayList<>();
			for(int i=0; i< disable.size(); i++) {
				Integer id = disable.get(i);
				FileServer testServer = fileServerService.getById(id);
				if (testServer == null) {
					temp.add(id);
					System.out.println("server(id-"+id+") has been removed.");
				} else if (fileServerUtils.test(testServer)) {
					temp.add(id);
					System.out.println("server("+testServer.getName()+") is enable again.");
				}
			}
			disable.removeAll(temp);
		}
    }
	
}
